package com.whq.mvc.service.impl;

import com.whq.mvc.dao.OrderDoMapper;
import com.whq.mvc.dao.SequenceDOMapper;
import com.whq.mvc.entity.OrderDo;
import com.whq.mvc.entity.SequenceDO;
import com.whq.mvc.resp.BusinessException;
import com.whq.mvc.resp.EmBusinessError;
import com.whq.mvc.service.ItemService;
import com.whq.mvc.service.OrderService;
import com.whq.mvc.service.UserService;
import com.whq.mvc.service.model.ItemModel;
import com.whq.mvc.service.model.OrderModel;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionSynchronization;
import org.springframework.transaction.support.TransactionSynchronizationManager;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Objects;

@Service
public class OrderServiceImpl implements OrderService {

    @Autowired
    private ItemService itemService;

    @Autowired
    private UserService userService;

    @Autowired
    private SequenceDOMapper sequenceDOMapper;

    @Autowired
    private OrderDoMapper orderDoMapper;

    @Override
    @Transactional
    public OrderModel createOrder(Integer userId, Integer itemId, Integer promoId, Integer amount) throws BusinessException {
        //ItemModel itemModel = itemService.getItemById(itemId);
        ItemModel itemModel = itemService.getItemByIdInCache(itemId);   //修改为通过redis缓存获取
        if (amount <= 0 || amount > 99) {
            throw new BusinessException(EmBusinessError.PARAMETER_VALIDATION_ERROR, "数量信息不合法");
        }
        //扣减库存
        boolean result = itemService.decreaseStock(itemId, amount);
        if (!result) {
            throw new BusinessException(EmBusinessError.STOCK_NOT_ENOUGH);
        }

        //订单入库
        OrderModel orderModel = new OrderModel();
        orderModel.setUserId(userId);
        orderModel.setItemId(itemId);
        orderModel.setAmount(amount);
        if (promoId != null) {
            orderModel.setPromoId(promoId);
            orderModel.setItemPrice(itemModel.getPromoModel().getPromoItemPrice());
        } else {
            orderModel.setItemPrice(itemModel.getPrice());
        }
        orderModel.setOrderPrice(orderModel.getItemPrice().multiply(new BigDecimal(amount)));//订单价格
        orderModel.setId(generateOrderNo());
        OrderDo orderDo = this.convertFromOrderModel(orderModel);

        orderDoMapper.insertSelective(orderDo); //生成订单数据
        itemService.increaseSales(itemId, amount);   //更新销量

        //事务完全提交之后，再发消息扣减库存
        TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {
            @Override
            public void afterCommit() {
                boolean sendMsgSuccess = itemService.asyncDecreaseStock(itemId, amount);    //异步更新数据库存数量，走消息队列
                if (!sendMsgSuccess) {
                    itemService.increaseStock(itemId, amount);
                }
            }
        });

        return orderModel;
    }

    @Transactional
    public String generateOrderNo() {
        StringBuilder sb = new StringBuilder(16);
        LocalDateTime now = LocalDateTime.now();
        String nowDate = now.format(DateTimeFormatter.ISO_DATE).replace("-", "");
        sb.append(nowDate);

        int sequence = 0;
        SequenceDO sequenceDo = sequenceDOMapper.getSequenceByName("order_info");
        sequence = sequenceDo.getCurrentValue();
        int step = sequenceDo.getStep();
        sequenceDo.setCurrentValue(sequence + step);
        sequenceDOMapper.updateByPrimaryKeySelective(sequenceDo);

        String sequenceStr = String.valueOf(sequence);
        for (int i = 0; i < 6 - sequenceStr.length(); i++) {
            sb.append("0");
        }
        sb.append(sequenceStr);

        sb.append("00");    //分库分表位 暂时写死00
        return sb.toString();
    }

    private OrderDo convertFromOrderModel(OrderModel orderModel) {
        if (Objects.isNull(orderModel)) {
            return null;
        }
        OrderDo orderDo = new OrderDo();
        BeanUtils.copyProperties(orderModel, orderDo);
        orderDo.setItemPrice(orderModel.getItemPrice().doubleValue());
        orderDo.setOrderPrice(orderModel.getOrderPrice().doubleValue());
        return orderDo;
    }
}
